﻿using AspNetId4Web.Data;
using AspNetId4Web.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

namespace AspNetId4Web
{
    /// <summary>
    /// 手机验证码服务
    /// </summary>
    public class PhoneCodeService
    {
        private readonly IMemoryCache _memoryCache;
        private readonly IServiceProvider _serviceProvider;
        private readonly ILogger _logger;

        public PhoneCodeService(
            IMemoryCache memoryCache,
            IServiceProvider serviceProvider,
            ILogger<PhoneCodeService> logger)
        {
            _memoryCache = memoryCache;
            _serviceProvider = serviceProvider;
            _logger = logger;
        }

        /// <summary>
        /// 发送验证码到手机号
        /// </summary>
        /// <param name="phoneNumber"></param>
        /// <returns></returns>
        public async Task<(bool IsError, string Msg)> SendPhoneCode(string phoneNumber)
        {
            //根据手机号获取用户信息
            var appUser = await GetUserByPhoneNumberAsync(phoneNumber);
            if (appUser == null)
            {
                return (true, "手机号无效");
            }

            //发送验证码到手机号，需要调用短信服务平台Web Api，这里模拟发送
            string verificationCode = (new Random()).Next(1000, 9999).ToString();

            //验证码缓存10分钟
            _memoryCache.Set(phoneNumber, verificationCode, TimeSpan.FromMinutes(10));

            _logger.LogInformation($"发送验证码{verificationCode}到手机号{phoneNumber}, 有效期{DateTime.Now.AddMinutes(10)}");

            return (false, "发送验证码成功");
        }

        /// <summary>
        /// 手机验证码登录
        /// </summary>
        /// <param name="phoneNumber">手机号</param>
        /// <param name="verificationCode">验证码</param>
        /// <returns></returns>
        public async Task<(bool IsError, string Msg)> PhoneCodeLogin(string phoneNumber, string verificationCode)
        {
            try
            {
                //获取手机号对应的缓存验证码
                if (!_memoryCache.TryGetValue(phoneNumber, out string cacheVerificationCode))
                {
                    //如果获取不到缓存验证码，说明手机号不存在，或者验证码过期，但是发送验证码时已经验证过手机号是存在的，所以只能是验证码过期
                    return (true, "验证码过期");
                }

                if (verificationCode != cacheVerificationCode)
                {
                    return (true, "验证码错误");
                }

                //根据手机号获取用户信息
                var appUser = await GetUserByPhoneNumberAsync(phoneNumber);
                if (appUser == null)
                {
                    return (true, "手机号无效");
                }

                //验证通过
                return (false, "验证通过");
            }
            catch (Exception ex)
            {
                return (true, ex.Message);
            }
        }

        /// <summary>
        /// 根据手机号获取用户信息
        /// </summary>
        /// <param name="phoneNumber">手机号</param>
        /// <returns></returns>
        public async Task<ApplicationUser> GetUserByPhoneNumberAsync(string phoneNumber)
        {
            using var scope = _serviceProvider.CreateScope();
            var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

            var appUser = await context.Users.AsNoTracking()
                 .FirstOrDefaultAsync(x => x.PhoneNumber == phoneNumber);

            return appUser;
        }
    }
}
